**************************************************************************************
** title:		dataset coding for 'Is there a `Youthquake'? 						**
** authors:		ruth dassonneville & ian mcallister 								**
** date:		February 2025 														**
** machine:		MacOS Sonoma 14.4													**
** software:	Stata 18 															**
**************************************************************************************
			

* -------------
* preamble 
* -------------

	/* before running this dofile, download the CHES data (we used version 1999-2019_CHES_dataset_means(v3))
	and download the EES 2019 voter survey that is available at http://europeanelectionstudies.net/european-election-studies/ees-2019-study/voter-study-2019 and store
	the data in the "youthquake-replication/data" folder on your local drive using the following names
	- 1999-2019_CHES_dataset_means(v3).dta
	- ZA7581_v2-0-1.dta
	*/

	** install packages (uncomment if not installed yet)
	/* install xfill package (user-written)*/
	*net from https://www.sealedenvelope.com/

	** set working directory first
	cd "~/Dropbox/youthquake-replication/data/"
	
	** restrict CHES data to 2019 data for merge with EES 2019 voter survey
	use "1999-2019_CHES_dataset_means(v3)", clear
	keep if year==2019
	rename party partyabbreviation
	save "ches-2019.dta", replace

	** load EES voter survey data 
	use "ZA7581_v2-0-1.dta", clear

* ----------------------------------------
* coding of variables in wide dataset 
* ----------------------------------------

	** PTV variables
	recode q10_1 q10_2 q10_3 q10_4 q10_5 q10_6 q10_7 q10_8 q10_9 q10_10 (97=.) (98=.) (96=.)

	egen maxPTV=rowmax(q10_1 q10_2 q10_3 q10_4 q10_5 q10_6 q10_7 q10_8 q10_9 q10_10)
	rowsort(q10_1 q10_2 q10_3 q10_4 q10_5 q10_6 q10_7 q10_8 q10_9 q10_10 ) , gen(rankedptv1-rankedptv10) descending highmissing 
	
	rename q10_1 ptv1
	rename q10_2 ptv2
	rename q10_3 ptv3
	rename q10_4 ptv4
	rename q10_5 ptv5
	rename q10_6 ptv6
	rename q10_7 ptv7
	rename q10_8 ptv8
	rename q10_9 ptv9
	rename q10_10 ptv10
	
	gen indifference=10-(rankedptv1-rankedptv2)
	gen difference=(rankedptv1-rankedptv2)

* ---------------------------	
* reshape to long format	
* ---------------------------	

	/* The EES asks respondents to indicate their PTV for up to 10 parties,
	which are separate variables. We want to stack those responses as
	rows in the dataset, so the focus moves to the respondent-party dyad
	level of observation. For each respondent there will be up to 10 rows */
	
	gen id=string(countrycode) + "_" + string(respid)
	reshape long ptv, i(id) j(party)


* --------------------------------------------	
* merge with CHES data for info on parties	
* --------------------------------------------	

	/* To merge the EES voter survey with the CHES data we first have to create 
	a key variable to merge the data on. We manually code the key variable party_id
	in the EES voter survey data so it corresponds to the CHES party_id value for that party.
	
	Information on which parties correspond to the variables in the PTV measures
	is retrieved from the 'party list'-sheet that can be found here 
	http://europeanelectionstudies.net/european-election-studies/ees-2019-study/voter-study-2019.
	
	CHES party_id code value is retrieved from the Chapel Hill Expert Survey - Trend File 1999-2019
	Codebook. 
	
	For some parties there is no match between the party name in the EES voter survey data and the 
	parties included in the CHES data. For those parties the code line is disactivated with an '*' */
	
	** Austria (countrycode==1040)
	gen party_id=1302 if party==1 & countrycode==1040		// ÖVP
	replace party_id=1301 if party==2 & countrycode==1040	// SPÖ
	replace party_id=1306 if party==3 & countrycode==1040	// NEOS
	replace party_id=1304 if party==4 & countrycode==1040	// Die Grünen
	replace party_id=1303 if party==5 & countrycode==1040	// FPÖ
	*replace party_id= if party==6 & countrycode==1040	// Jetzt - Liste Pilz/Europa
	
	** Belgium - Flanders (countrycode==1056, meta_lang_be==1)
	replace party_id=119 if party==1 & countrycode==1056 & meta_lang_be==1	// PVDA/PTB
	replace party_id=109 if party==2 & countrycode==1056 & meta_lang_be==1	// CD&V
	replace party_id=103 if party==3 & countrycode==1056 & meta_lang_be==1	// SP.a
	replace party_id=107 if party==4 & countrycode==1056 & meta_lang_be==1	// Open VLD
	replace party_id=110 if party==5 & countrycode==1056 & meta_lang_be==1	// N-VA
	replace party_id=105 if party==6 & countrycode==1056 & meta_lang_be==1	// Groen
	replace party_id=112 if party==7 & countrycode==1056 & meta_lang_be==1	// Vlaams Belang
	
	** Belgium - Wallonia (countrycode==1056, meta_lang_be==1)
	replace party_id=102 if party==1 & countrycode==1056 & meta_lang_be==2	// PS
	replace party_id=106 if party==2 & countrycode==1056 & meta_lang_be==2	// MR
	replace party_id=108 if party==3 & countrycode==1056 & meta_lang_be==2	// cdH
	replace party_id=104 if party==4 & countrycode==1056 & meta_lang_be==2	// ECOLO
	replace party_id=115 if party==5 & countrycode==1056 & meta_lang_be==2	// FN
	replace party_id=119 if party==6 & countrycode==1056 & meta_lang_be==2	// PTB
	replace party_id=111 if party==7 & countrycode==1056 & meta_lang_be==2	// DéFI * note: coded as successor of FDF
	
	** Cyprus (countrycode==1196)
	replace party_id=4003 if party==1 & countrycode==1196 // Progressive Party of the Working People
	replace party_id=4001 if party==2 & countrycode==1196 // Democratic Rally
	replace party_id=4004 if party==3 & countrycode==1196 // Democratic Party
	replace party_id=4005 if party==4 & countrycode==1196 // United Democratic Union of Centre * note: corresponds to Movement for social democracy EDEK
	replace party_id=4006 if party==5 & countrycode==1196 // Ecological and Environmental Movement (Cyprus Green Party)
	replace party_id=4009 if party==6 & countrycode==1196 // National Popular Front
	
	** Germany (countrycode==1276)
	replace party_id=301 if party==1 & countrycode==1276 // CDU/CSU * note that CDU code is used, CSU = 308, but cannot be distinguished in EES voter survey
	replace party_id=302 if party==2 & countrycode==1276 // SPD
	replace party_id=303 if party==3 & countrycode==1276 // FDP
	replace party_id=304 if party==4 & countrycode==1276 // Die Grünen
	replace party_id=306 if party==5 & countrycode==1276 // Die Linke
	replace party_id=310 if party==6 & countrycode==1276 // AFD
	replace party_id=311 if party==7 & countrycode==1276 // Piraten
	
	* Denmark (countrycode==1208)
	replace party_id=201 if party==1 & countrycode==1208 // Socialdemokraterne
	replace party_id=211 if party==2 & countrycode==1208 // Venstre
	replace party_id=215 if party==3 & countrycode==1208 // Dansk Folkeparti
	replace party_id=202 if party==4 & countrycode==1208 // Radikale Venstre
	replace party_id=206 if party==5 & countrycode==1208 // Socialistisk Folkeparti
	replace party_id=213 if party==6 & countrycode==1208 // Enhedslisten
	replace party_id=203 if party==7 & countrycode==1208 // Det Konservative Folkeparti
	
	** Finland (countrycode==1246)
	replace party_id=1401 if party==1 & countrycode==1246 // Suomen Sosialidemkoraattinen Puolue (SDP)
	replace party_id=1405 if party==2 & countrycode==1246 // Perussuomalaiset (Perus/PS)
	replace party_id=1402 if party==3 & countrycode==1246 // Kansallinen Kokoomus (KOK)
	replace party_id=1403 if party==4 & countrycode==1246 // Suomen Keskusta (KESK)
	replace party_id=1408 if party==5 & countrycode==1246 // Vihreä Liitto (VIHR)
	replace party_id=1404 if party==6 & countrycode==1246 // Vasemmistoliitto (VAS)
	replace party_id=1406 if party==7 & countrycode==1246 // Suomen ruotsalainen kansanpuolue (RKP)
	
	** France (countrycode==1250)
	replace party_id=609 if party==1 & countrycode==1250 // Les Républicains (LR)
	replace party_id=602 if party==2 & countrycode==1250 // Parti socialiste (PS)
	replace party_id=610 if party==3 & countrycode==1250 // Rassemblement national (RN)
	replace party_id=605 if party==4 & countrycode==1250 // Europe Ecologie - Les Verts (EELV)
	replace party_id=627 if party==5 & countrycode==1250 // France insoumise (LFI)
	*replace party_id= if party==6 & countrycode==1250 // Génération.s
	replace party_id=626 if party==7 & countrycode==1250 // La République en Marche (LRM)
	
	** Greece (countrycode==1300)
	replace party_id=403 if party==1 & countrycode==1300 // Coalition of the Radical Left
	replace party_id=402 if party==2 & countrycode==1300 // New Democracy
	replace party_id=415 if party==3 & countrycode==1300 // Golden Dawn
	replace party_id=401 if party==4 & countrycode==1300 // Panhellenic Socialist Movement/Movement for Change
	replace party_id=404 if party==5 & countrycode==1300 // Communist Party of Greece
	replace party_id=413 if party==6 & countrycode==1300 // The River
	replace party_id=412 if party==7 & countrycode==1300 // Independent Greeks
	
	** Ireland (countrycode==1372)
	replace party_id=702 if party==1 & countrycode==1372 // Fine Gael
	replace party_id=703 if party==2 & countrycode==1372 // Labour Party 
	replace party_id=701 if party==3 & countrycode==1372 // Fianna Fail
	replace party_id=705 if party==4 & countrycode==1372 // Green Party
	replace party_id=707 if party==5 & countrycode==1372 // Sinn Fein
	replace party_id=709 if party==6 & countrycode==1372 // Solidarity - People Before Profit
	
	** Italy (countrycode==1380)
	replace party_id=837 if party==1 & countrycode==1380 // Partito Democrtico (PD)
	replace party_id=815 if party==2 & countrycode==1380 // Forza Italia (FI)
	replace party_id=811 if party==3 & countrycode==1380 // Lega Salvini Premier * noted: coded as Lega Nord
	replace party_id=845 if party==4 & countrycode==1380 // Movimento 5 Stelle (M5S)
	replace party_id=842 if party==5 & countrycode==1380 // Sinistra
	*replace party_id= if party==6 & countrycode==1380 // "+Europa"
	replace party_id=844 if party==7 & countrycode==1380 // Fratelli d'Italia - Centrodestra Nazionale
	
	** Luxembourg (countrycode==1442)
	replace party_id=3801 if party==1 & countrycode==1442 // Chrëschtlech Sozial Vollekspartei (CSV)
	replace party_id=3804 if party==2 & countrycode==1442 // Lëtzebuerger Sozialistesch Aarbechterpartei (LSAP)
	replace party_id=3803 if party==3 & countrycode==1442 // Demokratesch Partei (DP)
	replace party_id=3802 if party==4 & countrycode==1442 // Déi Gréng
	replace party_id=3806 if party==5 & countrycode==1442 // Déi Lénk (DL )
	replace party_id=3805 if party==6 & countrycode==1442 // Alternativ Demokratesch Reformpartei (ADR)
	replace party_id=3807 if party==7 & countrycode==1442 // Piratepartei (PPL)
	
	** Malta (countrycode==1470)
	replace party_id=3701 if party==1 & countrycode==1470 // Partit Laburista
	replace party_id=3702 if party==2 & countrycode==1470 // Partit Nazzjonalista
	*replace party_id= if party==3 & countrycode==1470 // Alternattiva Demokratika
	*replace party_id= if party==4 & countrycode==1470 // Partit Demokratiku
	*replace party_id= if party==5 & countrycode==1470 // Imperu Ewropew
	
	** Netherlands (countrycode==1528)
	replace party_id=1003 if party==1 & countrycode==1528 // VVD 
	replace party_id=1017 if party==2 & countrycode==1528 // PVV
	replace party_id=1001 if party==3 & countrycode==1528 // CDA
	replace party_id=1004 if party==4 & countrycode==1528 // D66
	replace party_id=1005 if party==5 & countrycode==1528 // GroenLinks
	replace party_id=1014 if party==6 & countrycode==1528 // SP 
	replace party_id=1002 if party==7 & countrycode==1528 // PvdA
	replace party_id=1016 if party==8 & countrycode==1528 // Christen Unie-SGP * note: CU code is used, SGP code = 1006, voters cannot be distinguished in EES voter survey data
	replace party_id=1051 if party==9 & countrycode==1528 // Forum voor Democratie
	
	** Portugal (countrycode==1620)
	replace party_id=1206 if party==1 & countrycode==1620 // Partido Social Democrata (PSD)
	replace party_id=1202 if party==2 & countrycode==1620 // Centro Democratico e Social - Partido Popular (CDS-PP)
	replace party_id=1205 if party==3 & countrycode==1620 // Partido Socialista (PS)
	replace party_id=1201 if party==4 & countrycode==1620 // Coligaçao Democratica Unitaria (CDU)
	replace party_id=1208 if party==5 & countrycode==1620 // Bloco de Esquerda (BE)
	replace party_id=1250 if party==6 & countrycode==1620 // Pessoas, Animais, Natureza (PAN)
	
	** Spain (countrycode==1724)
	replace party_id=501 if party==1 & countrycode==1724 // Partido Socialista Obrero Espanol (PSOE)
	replace party_id=502 if party==2 & countrycode==1724 // Partido Popular (PP)
	replace party_id=525 if party==3 & countrycode==1724 // Unidas Podemos (UP)
	replace party_id=526 if party==4 & countrycode==1724 // Ciudadanos 
	replace party_id=527 if party==5 & countrycode==1724 // VOX
	replace party_id=511 if party==6 & countrycode==1724 // Ahora Repúblicas (Esquerra Republicana de Catalunya y otros) 
	*replace party_id= if party==7 & countrycode==1724 // Compromís per Europa/Compromiso por Europa * note: is an alliance of regional parties
	
	** Sweden (countrycode==1752)
	replace party_id=1602 if party==1 & countrycode==1752 // Socialdemokraterna (S)
	replace party_id=1605 if party==2 & countrycode==1752 // Moderaterna (M)
	replace party_id=1607 if party==3 & countrycode==1752 // Miljöpartiet de gröna (MP)
	replace party_id=1604 if party==4 & countrycode==1752 // Liberalerna (L)
	replace party_id=1603 if party==5 & countrycode==1752 // Centerpartiet (C)
	replace party_id=1610 if party==6 & countrycode==1752 // Sverigedemokraterna (SD)
	replace party_id=1606 if party==7 & countrycode==1752 // Kristdemokraterna (KD)
	replace party_id=1601 if party==8 & countrycode==1752 // Vänsterpartiet (VP)
	
	** United Kingdom (countrycode==1826)
	replace party_id=1101 if party==1 & countrycode==1826 // Conservative (Con)
	replace party_id=1102 if party==2 & countrycode==1826 // Labour Party (Lab)
	replace party_id=1104 if party==4 & countrycode==1826 // Liberal Democrats (LD)
	replace party_id=1107 if party==5 & countrycode==1826 // Green Party (GP)
	replace party_id=1105 if party==6 & countrycode==1826 // Scottish National Party (SNP)
	replace party_id=1108 if party==7 & countrycode==1826 // United Kingdom Independence Party (UKIP)
	replace party_id=1110 if party==8 & countrycode==1826 // The Brexit Party
	
	** merge in the CHES 2019 data - match on party_id key variable
	merge m:1 party_id using "ches-2019.dta"
	keep if _merge==3
	drop _merge

* -------------------------------------------	
* restrict dataset to specific countries	
* -------------------------------------------	

	drop if country==37		// dropping malta
	drop if country==40		// dropping cyprus	

* ----------------------------------------
* coding of variables in long dataset 
* ----------------------------------------	
	
	** party voted for (non-voters and those voting for parties for which no CHES info are coded as missing)
	recode Q7n (99=.) (98=.) (96=.) (90=.) (20=.) (0=.)
	gen votedforparty=1 if Q7n==party & Q7n!=.
	replace votedforparty=0 if Q7n!=party & Q7n!=. 
	
	** rescale eu position to 0-10 scale
	replace eu_position=((eu_position-1)/6)*10
	
	** create party info variables for the party the individual voted for
	gen family_voted=family if votedforparty==1		// CHES party family of party voted for
	gen lrgen_voted=lrgen if votedforparty==1		// CHES LR placement of party voted for
	gen lrecon_voted=lrecon if votedforparty==1		// CHES eco LR placement of party voted for
	gen galtan_voted=galtan if votedforparty==1		// CHES galtan placement of party voted for
	gen eu_voted=eu_position if votedforparty==1	// CHES eu placement of party voted for
	
	** recode party family --> more limited number of options
	recode family_voted (10=4)			// confessional parties grouped with christdem
	recode family_voted (9=.) (11=.)	// no family and agrarian/centre coded as missing
	recode family_voted (8=.)			// regionalist as missing
	
	label define familyl 1 "tan" 2 "cons" 3 "liberal" 4 "christdem" 5 "socialist" 6 "rad left" 7 "green" 
	label values family_voted familyl  
	label values family familyl
	
	** recode party family for object as well
	recode family (10=4)			// confessional parties grouped with christdem
	recode family (9=.) (11=.)		// no family and agrarian/centre coded as missing
	recode family (8=.)				// regionalist as missing 
	 
	** fill the info about party voted for so it appears in all respondent-rows 
	encode id, gen(id_num)
	xfill family_voted lrgen_voted lrecon_voted galtan_voted eu_voted, i(id_num)
	
	** create variables that capture distance between party voted for and party evaluated
	gen distance_lrgen=abs(lrgen-lrgen_voted)
	replace distance_lrgen=. if votedforparty==1
	gen distance_lrecon=abs(lrecon-lrecon_voted)
	replace distance_lrecon=. if votedforparty==1
	gen distance_galtan=abs(galtan-galtan_voted)
	replace distance_galtan=. if votedforparty==1
	gen distance_eu=abs(eu_position-eu_voted)
	replace distance_eu=. if votedforparty==1
	
	** create variables that are indicators of party system

	gen option_radicalright=1 if family==1		// radical right party
	xfill option_radicalright , i(country)		// fill all cells with 1 if at least 1 radical-right party evaluated in a country
	replace option_radicalright=0 if option_radicalright!=1 & family!=.
		
	
	** additional variables for individual-level heterogeneity
	
	recode EDU (99=.)
	
	gen female=1 if D3==2			// 'other' coded as missing > small N
	replace female=0 if D3==1
	
	gen agegroup=hAge
	
	gen workingclass=1 if D7==1
	replace workingclass=0 if D7==2 | D7==3 | D7==4	| D7==5 | D7==6		// any other class, from lower middle to upper + other
	
	
	** additional political attitudes
	recode  Q14_1 Q14_2 Q14_3 Q14_4 Q14_5 Q14_6 (98=.) (99=.)
	
	clonevar issue_nostateintervention=Q14_1
	clonevar issue_noredistribution=Q14_2
	clonevar issue_nosamesex=Q14_3
	clonevar issue_restrictprivacy=Q14_4
	gen issue_immigration=(10-Q14_5)		// reverse so higher values = pro restrictive immigration policies
	clonevar issue_ecovsenvironment=Q14_6
	
	factor issue_*, pcf		// note that environmental issue loads on economic dimension, not included in combined postion-measures
	alpha issue_nostateintervention issue_noredistribution 
	alpha issue_nosamesex issue_restrictprivacy issue_immigration	 
	
	gen economicviews=(issue_nostateintervention+issue_noredistribution)/2
	gen galtanviews=(issue_nosamesex+issue_restrictprivacy+issue_immigration)/3
	
	** alternative variables based on party voted for in NATIONAL election
	
	recode Q9n (99=.) (98=.) (96=.) (90=.) (20=.) (0=.) 
	gen votedforpartynat=1 if Q9n==party & Q9n!=.
	replace votedforpartynat=0 if Q9n!=party & Q9n!=. 
	
	gen family_votednat=family if votedforpartynat==1		// CHES party family of party voted for at national level
	gen lrgen_votednat=lrgen if votedforpartynat==1			// CHES LR placement of party voted for
	gen lrecon_votednat=lrecon if votedforpartynat==1		// CHES eco LR placement of party voted for
	gen galtan_votednat=galtan if votedforpartynat==1		// CHES galtan placement of party voted for
	
	recode family_votednat (10=4)			// confessional parties grouped with christdem
	recode family_votednat (9=.) (11=.)		// no family and agrarian/centre coded as missing
	recode family_votednat (8=.)			// regionalist as missing
	
	label values family_votednat familyl  
	
	xfill family_votednat lrgen_votednat lrecon_votednat galtan_votednat, i(id_num)
	
	gen distance_lrgennat=abs(lrgen-lrgen_votednat)
	replace distance_lrgennat=. if votedforpartynat==1
	gen distance_lreconnat=abs(lrecon-lrecon_votednat)
	replace distance_lreconnat=. if votedforpartynat==1
	gen distance_galtannat=abs(galtan-galtan_votednat)
	replace distance_galtannat=. if votedforpartynat==1

	** alternative variables based on PARTISANSHIP
	
	recode Q25n (99=.) (98=.) (96=.) (90=.) (20=.) (0=.) 
	gen pidparty=1 if Q25n==party & Q25n!=.
	replace pidparty=0 if Q25n!=party & Q25n!=. 
	
	gen family_pid=family if pidparty==1		// CHES party family of party identifying with
	gen lrgen_pid=lrgen if pidparty==1			// CHES LR placement of party identifying with
	gen lrecon_pid=lrecon if pidparty==1		// CHES eco LR placement of party identifying with
	gen galtan_pid=galtan if pidparty==1		// CHES galtan placement of party identifying with
	
	recode family_pid (10=4)			// confessional parties grouped with christdem
	recode family_pid (9=.) (11=.)		// no family and agrarian/centre coded as missing
	recode family_pid (8=.)				// regionalist as missing
	
	label values family_pid familyl  
	
	xfill family_pid lrgen_pid lrecon_pid galtan_pid, i(id_num)
	
	gen distance_lrgenpid=abs(lrgen-lrgen_pid)
	replace distance_lrgenpid=. if pidparty==1
	gen distance_lreconpid=abs(lrecon-lrecon_pid)
	replace distance_lreconpid=. if pidparty==1
	gen distance_galtanpid=abs(galtan-galtan_pid)
	replace distance_galtanpid=. if pidparty==1

* -------------------
* save dataset
* -------------------

	drop if country==38		// drop luxembourg (not included in 1999)

	save "ees-votersurvey-2019-coded.dta", replace

	
	
	

